import 'dart:math';
import 'package:doodle_dash/tank/MyTank.dart';
import 'package:flame/components.dart';
import 'package:flame/extensions.dart';

import 'EnemyTank.dart';
import 'MyTank.dart';

enum TankID { MASTER, ENEMY_ONE, ENEMY_TWO }

Map TankSprite = {
  TankID.ENEMY_ONE: ['tank/t_turret_green.webp', 'tank/t_body_green.webp'],
  TankID.ENEMY_TWO: ['tank/t_turret_sand.webp', 'tank/t_body_sand.webp'],
  TankID.MASTER: ['tank/t_turret_blue.webp', 'tank/t_body_blue.webp'],
};

Map TankBullet = {
  TankID.ENEMY_ONE: 'tank/bullet_green.webp',
  TankID.ENEMY_TWO: 'tank/bullet_sand.webp',
  TankID.MASTER: 'tank/bullet_blue.webp',
};

class TankFactory {
  static TankModel createTank(MyTank game, TankID id) {
    late TankModel tank;
    late String url1;
    late String url2;
    late Offset offset;
    if(id == TankID.MASTER){
      offset = Offset(game.screenSize.width / 2, game.screenSize.height / 2);
    }else{
      offset = Offset(Random().nextDouble() * game.screenSize.width * 0.6 + game.screenSize.width * 0.2, Random().nextDouble() * game.screenSize.height * 0.6 + game.screenSize.height * 0.2);
    }
    switch (id) {
      case TankID.ENEMY_ONE:
        url1 = TankSprite[TankID.ENEMY_ONE][0];
        url2 = TankSprite[TankID.ENEMY_ONE][1];
        tank = EnemyTank(game, url1, url2, offset, id);
        break;
      case TankID.ENEMY_TWO:
        tank = EnemyTank(
            game,
            TankSprite[TankID.ENEMY_TWO][0],
            TankSprite[TankID.ENEMY_TWO][1],
            offset, id);
      case TankID.MASTER:
        tank = Tank(
            game,
            TankSprite[TankID.MASTER][0],
            TankSprite[TankID.MASTER][1],
            offset, id);
        break;
    }
    return tank;
  }
}

abstract class TankModel {
  TankModel(this.game, this.url1, this.url2, this.position, this.tankId){
    initSpirte();
  }
  //坦克id
  late final TankID tankId;
  final MyTank game;
  //坦克图片
  final String url1, url2;
  late Sprite paoSprite, bodySprite;
  //坦克位置
  late Offset position;

  late Rect bodyRect;
  late Rect paoRect;

  ///随机生成路线用到
  final int seedNum = 50;
  final int seedRatio = 2;

  //主机坦克直线速度
  final double speed = 200;
  //主机坦克拐弯速度
  final double turnSpeed = 140;
  //敌方坦克直线速度
  final double speedEnemy = 150;
  //敌方坦克拐弯速度
  final double turnSpeedEnemy = 150 * 0.7;
  //身体角度
  double bodyAngle = 0;
  //炮台角度
  double paoAngle = 0;
  //身体目标角度
  double bodyAngleT = 0;
  //炮台目标角度
  double paoAngleT = 0;
  //是否存活
  final bool isLive = true;
  //移动到目标位置
  late Offset targetOffset;
  final double ration = 0.7;
  //获取发射位置
  Offset getBulletOffset();
  //获取子弹角度
  double getBulletAngle();

  void move(double dt);

  double moveDis = 0;

  @override
  void render(Canvas canvas) {
    if (!isLive) return;
    drawTank(canvas);
  }

  void initSpirte() async {
    paoSprite = await Sprite.load('$url1');
    bodySprite = await Sprite.load('$url2');
  }

  @override
  void update(double dt) {
    if (!isLive) return;
    move(dt);
    rotateBody(dt);
    rotatePao(dt);
  }

  void drawTank(Canvas canvas) {
    canvas.save();
    canvas.translate(position.dx, position.dy);
    canvas.rotate(bodyAngle);
    bodySprite.renderRect(canvas, bodyRect);
    canvas.rotate(paoAngle);
    paoSprite.renderRect(canvas, paoRect);
    canvas.restore();
  }

  void rotateBody(double dt) {
    final double rotateRate = pi * dt;
    if (bodyAngleT != 0) {
      if (bodyAngle < bodyAngleT) {
        if ((bodyAngleT - bodyAngle).abs() > pi) {
          bodyAngle = bodyAngle - rotateRate;
          if (bodyAngle < -pi) {
            bodyAngle += pi * 2;
          }
        } else {
          bodyAngle = bodyAngle + rotateRate;
          if (bodyAngle > bodyAngleT) {
            bodyAngle = bodyAngleT;
          }
        }
      }
      if (bodyAngle > bodyAngleT) {
        if ((bodyAngleT - bodyAngle).abs() > pi) {
          bodyAngle = bodyAngle + rotateRate;
          if (bodyAngle > pi) {
            bodyAngle -= pi * 2;
          }
        } else {
          bodyAngle = bodyAngle - rotateRate;
          if (bodyAngle < bodyAngleT) {
            bodyAngle = bodyAngleT;
          }
        }
      }
    }
  }

  void rotatePao(double dt) {
    final double rotationRate = pi * dt;

    if (paoAngleT != 0) {
      double localTargetTurretAngle = paoAngleT - bodyAngle;
      if (paoAngle < localTargetTurretAngle) {
        if ((localTargetTurretAngle - paoAngle).abs() > pi) {
          paoAngle = paoAngle - rotationRate;
          if (paoAngle < -pi) {
            paoAngle += pi * 2;
          }
        } else {
          paoAngle = paoAngle + rotationRate;
          if (paoAngle > localTargetTurretAngle) {
            paoAngle = localTargetTurretAngle;
          }
        }
      }
      if (paoAngle > localTargetTurretAngle) {
        if ((localTargetTurretAngle - paoAngle).abs() > pi) {
          paoAngle = paoAngle + rotationRate;
          if (paoAngle > pi) {
            paoAngle -= pi * 2;
          }
        } else {
          paoAngle = paoAngle - rotationRate;
          if (paoAngle < localTargetTurretAngle) {
            paoAngle = localTargetTurretAngle;
          }
        }
      }
    }
  }
}
